package com.arthas.client;

public class ArthasTool {
    /**
     * 获取arthas客户端连接
     *
     * @return
     */
    public static ArthasClient getClient() {
        ArthasClient client = new ArthasClient();
        if (!client.isConnected()) {//本地连接,不存在网络问题
            System.out.println("连接arthas失败,请检查arthas是否启动.");
            return null;
        }
        return client;
    }

    /**
     * 获取arthas客户端连接
     *
     * @return
     */
    public static ArthasClient getClient(String host, int port) {
        ArthasClient client = new ArthasClient(host, port);
        if (!client.isConnected()) {//本地连接,不存在网络问题
            System.out.println("连接arthas失败,请检查arthas是否启动.");
            return null;
        }
        return client;
    }

    /**
     * 获取classLoader,不知道classLoader有的类可能就找不到
     *
     * @param client telnet客户端
     * @param cls    类名
     * @return
     */
    public static String getClassLoader(ArthasClient client, String cls) {
        String rtn = client.sendCommand("sc -d " + cls + " | grep classLoaderHash");
        if (rtn != null && rtn.contains("classLoaderHash")) {
            if (rtn.contains("\n")) {//如果这个类有多个父类会返回多行
                rtn = rtn.substring(0, rtn.indexOf("\n"));//只取一行
            }
            return rtn.replace("classLoaderHash", "").trim();
        }
        return null;
    }

    /**
     * 返回移除String标签
     *
     * @param cmd
     * @return
     */
    public static String removeStringLebal(String cmd) {
        //还是有命令太长返回多余回显命令的,找标签截取,结尾]暂时-1处理,可能字符不是]结尾了
        int index = cmd.indexOf("@String[");
        return cmd.substring(index + 8, cmd.length() - 1);
    }

    /**
     * 获取sysprop命令返回的系统属性
     *
     * @param client
     * @param type
     * @return
     */
    public static String getSysprop(ArthasClient client, String type) {
        String rtn = client.sendCommand("sysprop | grep " + type);
        if (rtn != null && rtn.contains(type)) {
            if (rtn.contains("\n")) {//如果有多行,不一定有,只是参考getClassLoader方法
                rtn = rtn.substring(0, rtn.indexOf("\n"));//只取一行
            }
            return rtn.replace(type, "").trim();
        }
        return null;
    }

    /**
     * @param client
     * @param cls
     * @param directory 指定输出目录,注意转义目录分隔符。指定目录是为了保证目录路径不存在空格,正则处理路径会用到不可见字符
     * @return
     */
    public static String dumpClass(ArthasClient client, String cls, String directory) {
        String rtn = client.sendCommand("dump -d '" + directory + "' " + cls);
        return getDumpPath(rtn);
    }

    /**
     * 用于解析dump命令返回的class保存path
     *
     * @param rtn
     * @return
     */
    private static String getDumpPath(String rtn) {
        String[] rtns = rtn.split("\n");
        String tmp;
        for (int i = 0; i < rtns.length; i++) {
            tmp = rtns[i].trim().replaceAll("\\s+", " ");
            if (tmp.equals("HASHCODE CLASSLOADER LOCATION") && i + 1 < rtns.length) {
                tmp = rtns[i + 1].trim().replaceAll("\\s+", " ");
                String[] tmps = tmp.split(" ");
                if (tmps.length == 3) {
                    return tmps[2];
                }
            }
        }
        return null;
    }
}
